#include "./Console.h"

void initDataBase(const char *bookListFilename, const char *accountListFilename, const char *recordListFilename)
{
    bookList = BookListType_BookListType(bookListFilename);
    accountList = AccountListType_AccountListType(accountListFilename);
    recordList = RecordListType_RecordListType(recordListFilename);
}

int UI_menuList(const char *str)
{
    ListType *list = Str_split(str, ",", 0);
    int focus = 0;
    printList(list, focus);
    while (1)
    {
        if (kbhit())
        {
            int ch = getch();
            if (ch == 13 /*Enter*/)
            {
                ListType_free(list);
                return focus;
            }
            else if (ch == 72 /*up*/)
            {
                focus = (focus + list->size - 1) % list->size;
            }
            else if (ch == 80 /*down*/)
            {
                focus = (focus + 1) % list->size;
            }
            printList(list, focus);
        }
    }
}
void printList(ListType *list, int focus)
{
    system("cls");
    printf("* 使用上下箭头控制选项,Enter以确定选择\n");
    int i = 0;
    for (ListNode *p = list->head; p != NULL; p = p->next, i++)
    {
        if (i == focus)
        {
            printf("|                           * %-30s|\n", p->ptr);
        }
        else
        {
            printf("|                             %-30s|\n", p->ptr);
        }
    }
}

void UI_homePage()
{
    while (1)
    {
        int focus = UI_menuList("学生用户登录,管理员用户登录,学生用户注册,退出");
        switch (focus)
        {
        case 0:
            UI_Stu_Login();
            break;
        case 1:
            UI_Root_Login();
            break;
        case 2:
            UI_Stu_Regist();
            break;
        case 3:
            system("cls");
            if (UI_confirm("是否确认退出？"))
            {
                system("cls");
                return;
            }
            else
            {
                break;
            }
        default:
            printf("error");
            break;
        }
    }
}

void UI_Stu_Login()
{
    int time = 0;
    while (1)
    {
        system("cls");
        printf("账号:\n");
        char *id = Str_lineFromStdin();
        printf("密码:\n");
        char *password = Str_lineFromStdin();
        ListNode *tmp = AccountListType_query(accountList, id);
        if (tmp == NULL)
        {
            printf("该账号不存在\n");
            if (!UI_confirm("是否再次尝试？"))
                return;
            else
                continue;
        }
        if (strcmp(AccountType_ListNode(tmp)->password, password) == 0)
        {
            printf("密码正确,正在进入借书系统\n");
            Sleep(1000);
            UI_Stu_Func(AccountType_ListNode(tmp)->id);
            return;
        }
        else
        {
            time++;
            if (time > 3)
            {
                autoexit();
            }
            printf("已错误输入密码%d次\n", time);
            if (UI_exit())
            {
                return;
            }
            else
            {
                continue;
            }
        }
    }
}
void autoexit()
{
    system("cls");
    printf("系统将在3秒后退出");
    Sleep(1000);
    system("cls");
    printf("系统将在2秒后退出");
    Sleep(1000);
    system("cls");
    printf("系统将在1秒后退出");
    Sleep(1000);
    system("cls");
    exit(1);
}

void autoreturn(const char *printstr)
{
    printf("%s\n", printstr);
    system("cls");
    printf("将在3秒后自动返回");
    Sleep(1000);
    system("cls");
    printf("将在2秒后自动返回");
    Sleep(1000);
    system("cls");
    printf("将在1秒后自动返回");
    Sleep(1000);
    system("cls");
    exit(1);
}
void UI_Root_Login()
{
    int time = 0;
    while (1)
    {
        system("cls");
        char *id = "admin";
        printf("管理员密码:\n");
        char *password = Str_lineFromStdin();
        ListNode *tmp = AccountListType_query(accountList, id); // 引用类型，不需要释放
        if (tmp == NULL)
        {
            printf("管理员账号不存在\n");
            if (!UI_confirm("是否再次尝试？"))
                return;
            else
                continue;
        }
        if (strcmp(AccountType_ListNode(tmp)->password, password) == 0)
        {
            printf("密码正确,正在进入管理系统\n");
            Sleep(1000);
            UI_Root_Func();
            return;
        }
        else
        {
            time++;
            if (time > 3)
            {
                autoexit();
            }
            printf("已错误输入密码%d次\n", time);
            if (UI_exit())
            {
                return;
            }
            else
            {
                continue;
            }
            Sleep(1000);
        }
    }
}
void UI_Stu_Regist()
{
    while (1)
    {
        system("cls");
        printf("学生注册\n");
        printf("请输入id: \n");
        char *id = Str_lineFromStdin();
        if (AccountListType_query(accountList, id) != NULL)
        {
            if (UI_confirm("id已经存在，重新输入？"))
                continue;
            else
                return;
        }
        if (Str_isSpace(id))
        {
            if (UI_confirm("id不合法，继续输入？"))
                continue;
            else
                return;
        }
        printf("请输入姓名: \n");
        char *name = Str_lineFromStdin();
        if (AccountListType_query(accountList, name) != NULL)
        {
            if (UI_confirm("姓名已经存在，重新输入？"))
                continue;
            else
                return;
        }
        if (Str_isSpace(name))
        {
            if (UI_confirm("姓名不合法，继续输入？"))
                continue;
            else
                return;
        }
        printf("密码：\n");
        char *passwd = Str_lineFromStdin();
        printf("请确认密码：\n");
        char *repasswd = Str_lineFromStdin();
        while (strcmp(passwd, repasswd) != 0)
        {
            printf("两次密码不同,请重新输入密码：\n");
            passwd = Str_lineFromStdin();
            printf("请确认密码：\n");
            repasswd = Str_lineFromStdin();
        }
        AccountType *account = malloc(sizeof(AccountType));
        account->name = name;
        account->id = id;
        account->password = passwd;
        account->limit = 2;
        account->count = 0;
        ListType_insert(accountList->list, NULL, account);
        AccountListType_write(accountList);
        return;
    }
}
void UI_Stu_Func(const char *id)
{
    while (1)
    {
        int focus = UI_menuList("借书,还书,续借,查询当前已借书籍,查询可借书籍,查询书籍,返回");
        switch (focus)
        {
        case 0:
            UI_Stu_borrowBook(id);
            break;
        case 1:
            UI_Stu_returnBook(id);
            break;
        case 2:
            UI_Stu_renewNook(id);
            break;
        case 3:
            UI_Stu_bookBorrowed(id);
            break;
        case 4:
            UI_Stu_bookAvailable();
            break;
        case 5:
            UI_Stu_searchBook();
            break;
        case 6:
            system("cls");
            return;
            break;
        default:
            printf("error");
            break;
        }
    }
}

void UI_Stu_bookBorrowed(const char *id)
{
    system("cls");
    ListType *list = RecordListType_queryUser(recordList, id);
    if (!list->size)
    {
        printf("还没有借阅任何图书\n");
    }
    else
    {
        int cc = 1;
        for (ListNode *ite = list->head; ite; ite = ite->next, cc++)
        {
            RecordType *record = RecordType_ListNode(ite);
            char *CSVStr = RecordType_toCSVStr(record);
            printf("借书记录%d: %s\n", cc, CSVStr);
            free(CSVStr);
            ListNode *bookNode = BookListType_queryById(bookList, record->bookId);
            char *bookCSVStr = BookType_toCSVStr(BookType_ListNode(bookNode));
            printf("%s\n\n", bookCSVStr);
            free(bookCSVStr);
        }
    }
    printf("按Esc退出");
    int c = getch();
    while (c != 27)
        c = getch();
}
void UI_Stu_bookAvailable()
{
    while (1)
    {
        system("cls");
        printf("输入查询词条: ");
        char *str = Str_lineFromStdin();
        ListType *tmplist = BookListType_queryAvailable(bookList, str);
        if (tmplist->size == 0)
        {
            printf("未找到\n");
        }
        else
        {
            for (ListNode *ite = tmplist->head; ite; ite = ite->next)
            {
                printf("%s\n", BookType_toCSVStr(BookType_ListNode(ite)));
            }
        }
        if (UI_confirm("是否重新查找？"))
        {
            continue;
        }
        else
        {
            return;
        }
    }
}
void UI_Stu_borrowBook(const char *id)
{
    while (1)
    {
        system("cls");
        AccountType *account = AccountType_ListNode(AccountListType_query(accountList, id));
        if (account->count == account->limit)
        {
            if (UI_confirm("已经达到借阅上限，是否还书？"))
                UI_Stu_returnBook(id);
            return;
        }
        printf("请输入要借的书id: ");
        char *bookId = Str_lineFromStdin();
        ListNode *bookNode = BookListType_queryById(bookList, bookId);
        if (bookNode)
        {
            BookType *book = BookType_ListNode(bookNode);
            if (book->currentQuantity)
            {
                if (RecordListType_query(recordList, bookId, id) != NULL)
                {
                    if (UI_confirm("这本书已经被你借阅了，请勿重复借阅，继续借书吗？"))
                        continue;
                    else
                        return;
                }
                else
                {
                    RecordListType_borrow(recordList, bookList, accountList, bookId, id);
                    if (UI_confirm("借阅已经完成，继续借书吗？"))
                        continue;
                    else
                        return;
                }
            }
            else
            {
                if (UI_confirm("书本已经全部借出，重新输入？"))
                    continue;
                else
                    return;
            }
        }
        else
        {
            if (UI_confirm("书本并不存在，重新输入？"))
                continue;
            else
                return;
        }
    }
}

void UI_Stu_searchBook()
{
    while (1)
    {
        system("cls");
        printf("输入查询词条: ");
        char *str = Str_lineFromStdin();
        ListType *tmplist = BookListType_query(bookList, str);
        if (tmplist->size == 0)
        {
            printf("未找到\n");
        }
        else
        {
            for (ListNode *ite = tmplist->head; ite; ite = ite->next)
            {
                printf("%s\n", BookType_toCSVStr(BookType_ListNode(ite)));
            }
        }
        if (UI_confirm("是否重新查找？"))
        {
            continue;
        }
        else
        {
            return;
        }
    }
}

void UI_Stu_returnBook(const char *id)
{

    while (1)
    {
        system("cls");
        printf("输入要还的书的编号: ");
        char *bookId = Str_lineFromStdin();
        ListNode *ite = RecordListType_query(recordList, bookId, id);
        if (ite)
        {
            char *endDate = RecordType_ListNode(ite)->endDate;
            char *thisDate = Date_getTime(0);
            if (strcmp(endDate, thisDate) < 0)
            {
                free(thisDate);
                if (UI_confirm("本书已经超过还书期限，请在管理员处缴纳罚款后还书，继续还书吗？"))
                    continue;
                else
                    return;
            }
            else
            {
                free(thisDate);
            }
            RecordListType_return(recordList, bookList, accountList, bookId, id);
            if (UI_confirm("还书成功，继续还书吗？"))
                continue;
            else
                return;
        }
        else
        {
            if (!UI_confirm("书籍不存在或没有借阅这本书，重新输入吗？"))
                return;
        }
    }
}

void UI_Stu_renewNook(const char *id)
{
    while (1)
    {
        system("cls");
        printf("输入要续借的书的编号: ");
        char *bookId = Str_lineFromStdin();
        ListNode *ite = RecordListType_query(recordList, bookId, id);
        if (ite)
        {
            const char *endDate = RecordType_ListNode(ite)->endDate;
            char *thisDate = Date_getTime(0);
            if (strcmp(endDate, thisDate) < 0)
            {
                if (UI_confirm("本书已经超过还书期限，请在管理员处缴纳罚款后还书，继续续借吗？"))
                    continue;
                else
                    return;
            }
            RecordListType_continue(recordList, bookList, accountList, bookId, id);
            if (UI_confirm("续借成功，继续续借吗？"))
                continue;
            else
                return;
        }
        else
        {
            if (!UI_confirm("书籍不存在或没有借阅这本书，重新输入吗？"))
                return;
        }
    }
}

void UI_Root_Func()
{
    while (1)
    {
        int focus = UI_menuList("增加书籍,减少书籍,更改书籍信息,增加用户,减少用户,更改用户信息,返回主菜单");
        switch (focus)
        {
        case 0:
            UI_Root_addBook();
            break;
        case 1:
            UI_Root_removeBook();
            break;
        case 2:
            UI_Root_changeBookInfo();
            break;
        case 3:
            UI_Root_addUser();
            break;
        case 4:
            UI_Root_removeAccount();
            break;
        case 5:
            UI_Root_changeUserInfo();
            break;
        case 6:
            return;
        default:
            printf("error");
            break;
        }
    }
}

void UI_Root_addBook()
{
    char *CSVStr = UI_readRowInfo(BookSheetTitle);
    if (CSVStr == NULL)
        return;
    BookType *book = BookType_BookType(CSVStr);
    ListType_insert(bookList->list, NULL, book);
    BookListType_write(bookList);
    free(CSVStr);
}
void UI_Root_addUser()
{
    char *CSVStr = UI_readRowInfo(AccountSheetTitle);
    if (CSVStr == NULL)
        return;
    AccountType *account = AccountType_AccountType(CSVStr);
    ListType_insert(accountList->list, NULL, account);
    AccountListType_write(accountList);
    free(CSVStr);
}
void UI_Root_removeBook()
{
    while (1)
    {
        system("cls");
        printf("输入要删除书籍的id: ");
        char *id = Str_lineFromStdin();
        ListNode *tmp = BookListType_queryById(bookList, id);
        if (tmp == NULL)
        {
            if (UI_confirm("id不存在,是否重新输入？"))
            {
                continue;
            }
            else
            {
                return;
            }
        }
        if (UI_confirm("是否确认删除？"))
        {
            ListType_remove(bookList->list, tmp);
            BookListType_write(bookList);
            printf("删除成功!\n");
            if (UI_confirm("是否继续删除？"))
            {
                continue;
            }
            else
            {
                Sleep(1000);
                return;
            }
        }
        else
        {
            return;
        }
    }
}
/**
 * @brief 内部调用,更改书籍信息
 * @param book
 */
void changeBook(BookType *book)
{
    while (1)
    {
        system("cls");
        int focus = UI_menuList("图书编号,图书名称,图书作者,出版社,出版时间,价格,类别,总入库数量,当前库存数量,返回");
        /*"图书编号,图书名称,图书作者,出版社,出版时间,价格,类别,总入库数量,当前库存数量"*/
        if (focus == 9)
            return;
        system("cls");
        printf("将这一项修改为（空串以取消）: ");
        char *_change = Str_lineFromStdin();
        if (Str_isSpace(_change))
            continue;
        switch (focus)
        {
        case 0:
            book->id = _change;
            break;
        case 1:
            book->title = _change;
            break;
        case 2:
            book->author = _change;
            break;
        case 3:
            book->publisher = _change;
            break;
        case 4:
            book->publicationDate = _change;
            break;
        case 5:
            book->price = Str_parseDoubleFree(_change);
            break;
        case 6:
            book->category = _change;
            break;
        case 7:
            book->totalQuantity = Str_parseIntFree(_change);
            break;
        case 8:
            book->currentQuantity = Str_parseIntFree(_change);
            break;
        case 9:
            return;
            break;
        default:
            printf("error from changebook");
            break;
        }
    }
}
void UI_Root_changeBookInfo()
{
    while (1)
    {
        system("cls");
        printf("请输入要改动的书籍的id: ");
        char *id = Str_lineFromStdin();
        ListNode *tmp = BookListType_queryById(bookList, id);
        if (tmp == NULL)
        {
            if (UI_confirm("查无此书,是否重新输入id?"))
            {
                continue;
            }
            else
            {
                return;
            }
        }
        changeBook(tmp->ptr);
        BookListType_write(bookList);
        printf("修改成功！");
        if (UI_confirm("是否继续修改？"))
        {
            continue;
        }
        else
        {
            return;
        }
    }
}

void UI_Root_removeAccount()
{
    while (1)
    {
        system("cls");
        printf("请输入要删除的账号的id: ");
        char *id = Str_lineFromStdin();
        ListNode *tmp = AccountListType_query(accountList, id);
        if (tmp == NULL)
        {
            if (UI_confirm("该用户不存在,是否重新输入？"))
            {
                continue;
            }
            else
            {
                printf("正在返回");
                Sleep(1000);
                return;
            }
        }
        else
        {
            AccountListType_write(accountList);
            printf("删除成功！");
            if (UI_confirm("是否继续删除？"))
            {
                continue;
            }
            else
            {
                printf("正在返回");
                Sleep(1000);
                return;
            }
        }
    }
}
/**
 * @brief 内部函数，不可外部调用
 * @param stu 要更改的学生的账户
 */
void changeAccount(AccountType *stu)
{
    while (1)
    {
        int focus = UI_menuList("借阅卡号,借阅人姓名,借阅数量限制,已经借阅的数量,借阅密码,返回");
        /*"借阅卡号,借阅人姓名,借阅数量限制,已经借阅的数量,借阅密码"*/
        if (focus == 5 /* 返回 */)
            return;
        printf("请输入修改后的内容（空串以取消）： \n");
        char *_change = Str_lineFromStdin();
        if (Str_isSpace(_change))
            continue;
        switch (focus)
        {
        case 0:
            stu->id = _change;
            break;
        case 1:
            stu->name = _change;
            break;
        case 2:
            stu->limit = Str_parseIntFree(_change);
            break;
        case 3:
            stu->count = Str_parseIntFree(_change);
            break;
        case 4:
            stu->password = _change;
            break;
        case 5:
            return;
            break;
        default:
            printf("error from change()");
            break;
        }
    }
}
void UI_Root_changeUserInfo()
{
    while (1)
    {
        system("cls");
        printf("请输入要更改的账号的id: ");
        char *id = Str_lineFromStdin();
        ListNode *tmp = AccountListType_query(accountList, id);
        if (tmp == NULL)
        {
            if (UI_confirm("该用户不存在,是否重新输入？"))
            {
                continue;
            }
            else
            {
                printf("正在返回");
                Sleep(1000);
                return;
            }
        }
        else
        {
            changeAccount(tmp->ptr);
            AccountListType_write(accountList);
            printf("修改成功！");
            if (UI_confirm("是否继续修改？"))
            {
                continue;
            }
            else
            {
                return;
            }
        }
    }
}

int UI_confirm(const char *str)
{
    printf("%s (y/n) ", str);
    while (1)
    {
        int ch = getch();
        if (ch == 'y' || ch == 'Y')
        {
            printf("y\n");
            return 1;
        }
        else if (ch == 'n' || ch == 'N')
        {
            printf("n\n");
            return 0;
        }
    }
}
int UI_exit()
{
    printf("按Esc返回,按Enter重新输入\n");
    int c = getch();
    int flag = 0;
    while (c != 13 && c != 27)
    {
        if (flag == 0)
        {
            printf("请输入Esc或者Enter\n");
        }
        c = getch();
    }
    if (c == 27 /*Esc*/)
    {
        return 1;
    }
    else if (c == 13 /*Enter*/)
    {
        return 0;
    }
}

char *UI_readRowInfo(const char *str)
{
    ListType *list = Str_split(str, ",", 0);
    ListType *tmp = ListType_ListType(free);
    while (1)
    {
        system("cls");
        while (tmp->size)
            ListType_remove(tmp, tmp->head);
        for (ListNode *ite = list->head; ite; ite = ite->next)
        {
            printf("输入 %s: ", Str_ListNode(ite));
            ListType_insert(tmp, NULL, Str_CSVModeFree(Str_lineFromStdin()));
        }
        if (UI_confirm("是否确认此次输入？"))
            break;
        if (!UI_confirm("是否再次输入？"))
            return NULL;
    }
    char *res = Str_join(tmp, ",");
    ListType_free(list);
    ListType_free(tmp);
    return res;
}
